#ifndef GENIR_H
#define GENIR_H
/* genir 意思是产生中间表示 */

#include "inter_code.h"
#include "symbol.h"
#include "error.h"

typedef struct label_stack{
	struct list_head begin;
	struct list_head end;
}label_stack_t;

typedef struct case_info {
    var_t *case_val;
    inter_inst_t *case_entry;
    struct list_head entry;
} case_info_t;

var_t *gen_copy_assign(var_t *val);
var_t* gen_2_op(var_t *lval, symbol_e operator,  var_t* rval);
var_t *gen_1_op_left(var_t *val, symbol_e operator);
var_t *gen_1_op_right(var_t *val, symbol_e operator);
var_t *gen_arr(var_t *array, var_t *index, var_t *init);
var_t *gen_call(fun_t *fun, struct list_head *head);
void gen_parens_note(var_t *var);
void gen_var_init(var_t *var);
void gen_arr_init(var_t *arr);
void gen_if_head(var_t *cond, inter_inst_t **lb_else);
void gen_else_head(inter_inst_t *lb_else, inter_inst_t **lb_exit);
void gen_else_tail(inter_inst_t *lb_exit);
void label_stack_init(void);
void label_stack_destroy(void);
void push_labels(inter_inst_t *lb_begin, inter_inst_t *lb_end);
void gen_for_head(inter_inst_t **lb_for, inter_inst_t **lb_exit, 
				  inter_inst_t **lb_iter);
void gen_for_body(var_t *cond, inter_inst_t *lb_exit);
void gen_for_iter(inter_inst_t *lb_iter);
void gen_for_tail(inter_inst_t *lb_exit, inter_inst_t *lb_for);
void gen_while_head(inter_inst_t **lb_while, inter_inst_t **lb_exit);
void gen_while_cond(var_t *cond, inter_inst_t *lb_exit);
void gen_while_tail(inter_inst_t *lb_while, inter_inst_t *lb_exit);
void gen_do_while_head(inter_inst_t **lb_do, inter_inst_t **lb_exit);
void gen_do_while_tail(var_t *cond, inter_inst_t *lb_do, inter_inst_t *lb_exit);
void gen_switch_head(inter_inst_t **lb_exit);
void gen_switch_tail(inter_inst_t *lb_exit);
bool gen_case_entry(struct list_head *head, var_t *val);
void gen_case_select(struct list_head *head, var_t *cond, inter_inst_t *exit);
void gen_fun_entry(fun_t *fun);
void gen_fun_exit(fun_t *fun);
void gen_return(var_t *ret_val);
void gen_continue(void);
void gen_break(void);
void move_list_to_new_head(struct list_head *begin, struct list_head *new_head);
void put_list_back(struct list_head *head);
#endif